const { UserModel } = require('./db'); // 修正路径：从 ../db 改为 ./db

const rooms = new Map(); // roomId -> Set(socket.id)
const userInfoMap = new Map(); // roomId -> Map(socket.id -> {nickname, avatar, userId})
// 麦位映射：roomId -> Array(MAX_MIC).fill(null)
// 数组索引代表麦位号，值为 socket.id
const micMap = new Map(); 
const hostMap = new Map(); // roomId -> hostId
const muteMap = new Map(); // roomId -> Set(socket.id) 被禁麦用户
const backgroundMap = new Map(); // roomId -> backgroundUrl
const MAX_MIC = 8;

// 优化：添加快速查找用户所在房间的映射
const userRoomMap = new Map(); // socket.id -> roomId

module.exports = function(io) {
  // 配置Socket.io性能选项
  io.engine.pingTimeout = 10000; // 10秒超时
  io.engine.pingInterval = 5000; // 5秒ping间隔
  
  // 用户连接
  io.on('connection', (socket) => {
    console.log('用户已连接:', socket.id);

    // 获取房间列表
    socket.on('get-rooms', () => {
      const allRoomIds = Array.from(rooms.keys());
      socket.emit('rooms', allRoomIds);
    });

    // 创建房间
    socket.on('create-room', (roomId) => {
      if (!rooms.has(roomId)) {
        rooms.set(roomId, new Set());
        io.emit('room-created', roomId);
      }
    });

    // 加入房间（带昵称和头像）
    socket.on('join-room', (roomId, userInfo) => {
      // 优化：如果用户已在其他房间，先离开
      const currentRoom = userRoomMap.get(socket.id);
      if (currentRoom && currentRoom !== roomId) {
        handleLeaveRoom(socket, currentRoom);
      }
      
      socket.join(roomId);
      userRoomMap.set(socket.id, roomId); // 记录用户所在房间
      
      if (!rooms.has(roomId)) rooms.set(roomId, new Set());
      rooms.get(roomId).add(socket.id);
      if (!userInfoMap.has(roomId)) userInfoMap.set(roomId, new Map());
      
      // 修正了这里，使其能安全地处理 userInfo 不存在的情况，防止服务器崩溃
      const finalUserInfo = userInfo || {};
      userInfoMap.get(roomId).set(socket.id, {
        nickname: finalUserInfo.nickname || '匿名',
        avatar: finalUserInfo.avatar || '',
        userId: finalUserInfo._id || null,
      });
      
      // 主持人逻辑
      if (!hostMap.has(roomId)) {
        hostMap.set(roomId, socket.id);
        io.to(roomId).emit('host-info', socket.id);
      } else {
        io.to(socket.id).emit('host-info', hostMap.get(roomId));
      }
      
      // 初始化麦位/禁言列表
      if (!micMap.has(roomId)) micMap.set(roomId, Array(MAX_MIC).fill(null));
      if (!muteMap.has(roomId)) muteMap.set(roomId, new Set());

      // 如果有自定义背景，发送给新用户
      if (backgroundMap.has(roomId)) {
        socket.emit('background-changed', backgroundMap.get(roomId));
      }

      // 发送当前麦位和禁言列表给新用户
      socket.emit('mic-list', micMap.get(roomId));
      socket.emit('mute-list', Array.from(muteMap.get(roomId)));
      
      // 广播用户列表 - 优化：只发送必要信息
      const userList = Array.from(userInfoMap.get(roomId).entries()).map(([id, info]) => ({
        id, 
        nickname: info.nickname || '匿名',
        avatar: info.avatar || ''
      }));
      io.to(roomId).emit('user-list', userList);
      
      sendSystemMsg(roomId, `${finalUserInfo?.nickname || '匿名'} 加入了房间`);
      
      // 通知房间中的其他用户有新用户加入
      socket.to(roomId).emit('user-joined', socket.id);
    });

    // WebRTC 信令 - 处理 offer - 优化：减少日志输出
    socket.on('offer', ({ offer, to }) => {
      socket.to(to).emit('offer', {
        offer,
        from: socket.id
      });
    });

    // WebRTC 信令 - 处理 answer
    socket.on('answer', ({ answer, to }) => {
      socket.to(to).emit('answer', {
        answer,
        from: socket.id
      });
    });

    // WebRTC 信令 - 处理 ICE candidate - 优化：批量处理候选项
    let candidateQueue = {};
    let candidateTimer = {};
    
    socket.on('ice-candidate', ({ candidate, to }) => {
      // 如果没有队列，创建一个并设置定时器
      if (!candidateQueue[to]) {
        candidateQueue[to] = [];
        
        // 50ms后批量发送
        candidateTimer[to] = setTimeout(() => {
          if (candidateQueue[to] && candidateQueue[to].length > 0) {
            socket.to(to).emit('ice-candidates-batch', {
              candidates: candidateQueue[to],
              from: socket.id
            });
            delete candidateQueue[to];
            delete candidateTimer[to];
          }
        }, 50);
      }
      
      candidateQueue[to].push(candidate);
    });

    // 上麦
    socket.on('up-mic', (roomId, seatIndex) => {
      const micList = micMap.get(roomId) || Array(MAX_MIC).fill(null);
      if (!micMap.has(roomId)) micMap.set(roomId, micList);
      
      const muteList = muteMap.get(roomId) || new Set();
      
      if (muteList.has(socket.id)) {
        socket.emit('mic-rejected', { reason: 'muted' });
        return;
      }
      
      const isFull = !micList.some(s => s === null);
      if (isFull) {
        socket.emit('mic-full', MAX_MIC);
        return;
      }
      
      // 如果用户已在麦上，则忽略
      if (micList.includes(socket.id)) return;

      let targetIndex = -1;
      
      // 如果指定了座位
      if (typeof seatIndex === 'number' && seatIndex >= 0 && seatIndex < MAX_MIC) {
        if (micList[seatIndex] === null) {
          targetIndex = seatIndex;
        } else {
          // 指定位置有人，则自动分配
          targetIndex = micList.findIndex(s => s === null);
        }
      } else {
        // 未指定座位，自动寻找空位
        targetIndex = micList.findIndex(s => s === null);
      }

      if (targetIndex !== -1) {
        micList[targetIndex] = socket.id;
        micMap.set(roomId, micList);
        io.to(roomId).emit('mic-list', micList);
        
      const info = userInfoMap.get(roomId)?.get(socket.id);
      sendSystemMsg(roomId, `${info?.nickname || socket.id} 上麦了`);
      }
    });

    // 换座位
    socket.on('change-seat', ({ roomId, seatIndex }) => {
      const micList = micMap.get(roomId);
      if (!micList) return;

      const currentIndex = micList.indexOf(socket.id);
      // 检查用户是否在麦上，以及目标座位是否有效且为空
      if (currentIndex !== -1 && seatIndex >= 0 && seatIndex < MAX_MIC && micList[seatIndex] === null) {
        // 交换位置
        micList[currentIndex] = null; // 清空旧位置
        micList[seatIndex] = socket.id; // 占据新位置
        micMap.set(roomId, micList);
        io.to(roomId).emit('mic-list', micList);
      }
    });

    // 下麦
    socket.on('down-mic', (roomId) => {
      const micList = micMap.get(roomId);
      if (micList) {
        const index = micList.indexOf(socket.id);
        if (index !== -1) {
          micList[index] = null;
          micMap.set(roomId, micList);
          io.to(roomId).emit('mic-list', micList);

          const info = userInfoMap.get(roomId)?.get(socket.id);
          sendSystemMsg(roomId, `${info?.nickname || socket.id} 下麦了`);
        }
      }
    });

    // 禁麦
    socket.on('set-mute', ({ roomName, targetId }) => {
      if (hostMap.get(roomName) !== socket.id) return;
      if (!muteMap.has(roomName)) muteMap.set(roomName, new Set());
      muteMap.get(roomName).add(targetId);
      io.to(roomName).emit('mute-list', Array.from(muteMap.get(roomName)));
      // 被禁麦用户自动下麦
      const micList = micMap.get(roomName);
      if (micList) {
        const index = micList.indexOf(targetId);
        if (index !== -1) {
          micList[index] = null;
          micMap.set(roomName, micList);
          io.to(roomName).emit('mic-list', micList);
        }
      }
    });

    // 解禁
    socket.on('unset-mute', ({ roomName, targetId }) => {
      if (hostMap.get(roomName) !== socket.id) return;
      if (!muteMap.has(roomName)) muteMap.set(roomName, new Set());
      muteMap.get(roomName).delete(targetId);
      io.to(roomName).emit('mute-list', Array.from(muteMap.get(roomName)));
    });

    // 离开房间
    socket.on('leave-room', (roomId) => {
      handleLeaveRoom(socket, roomId);
    });

    // 发送消息
    socket.on('send-message', ({ roomId, message, userInfo }) => {
      // 优化：消息大小限制
      if (message && message.length > 500) {
        message = message.substring(0, 500) + '...';
      }
      
      io.to(roomId).emit('receive-message', {
        id: socket.id,
        message,
        nickname: userInfo?.nickname || '匿名',
        avatar: userInfo?.avatar || '',
        time: Date.now(),
        type: 'text'
      });
    });

    // 发送礼物
    socket.on('send-gift', async ({ roomId, gift, targetId }) => {
      try {
        const roomUsers = userInfoMap.get(roomId);
        if (!roomUsers) return;

        const senderInfo = roomUsers.get(socket.id);
        const receiverInfo = roomUsers.get(targetId);

        if (!senderInfo || !senderInfo.userId) {
          return socket.emit('gift-fail', { message: '无法找到发送者信息' });
        }
        if (!receiverInfo || !receiverInfo.userId) {
          return socket.emit('gift-fail', { message: '无法找到接收者信息' });
        }
        if (senderInfo.userId === receiverInfo.userId) {
          return socket.emit('gift-fail', { message: '不能给自己送礼物' });
        }

        const [sender, receiver] = await Promise.all([
          UserModel.findById(senderInfo.userId),
          UserModel.findById(receiverInfo.userId)
        ]);

        if (!sender) return socket.emit('gift-fail', { message: '数据库中找不到发送者' });
        if (!receiver) return socket.emit('gift-fail', { message: '数据库中找不到接收者' });
        
        if (sender.money < gift.price) {
          return socket.emit('gift-fail', { message: '金币不足！' });
        }

        sender.money -= gift.price;
        receiver.money += gift.price;

        await Promise.all([sender.save(), receiver.save()]);

        socket.emit('update-money', sender.money);
        io.to(targetId).emit('update-money', receiver.money);

        io.to(roomId).emit('receive-gift', {
          fromUser: {
            id: socket.id,
            nickname: senderInfo.nickname,
            avatar: senderInfo.avatar,
          },
          gift,
          receiverNickname: receiverInfo.nickname
        });

      } catch (error) {
        console.error('发送礼物时发生错误:', error);
        socket.emit('gift-fail', { message: '服务器内部错误' });
      }
    });

    // 更换房间背景
    socket.on('change-background', ({ roomId, background }) => {
      // 权限验证：只有房主才能更换背景
      if (hostMap.get(roomId) === socket.id) {
        backgroundMap.set(roomId, background); // 保存当前房间的背景
        io.to(roomId).emit('background-changed', background); // 广播给房间里的所有人
      }
    });

    // 用户断开时自动下麦、转让主持人、清理用户信息
    socket.on('disconnect', () => {
      const roomId = userRoomMap.get(socket.id);
      if (roomId) {
        handleLeaveRoom(socket, roomId);
      }
      userRoomMap.delete(socket.id);
      console.log('用户断开:', socket.id);
    });
  });

  // 处理用户离开房间的逻辑
  function handleLeaveRoom(socket, roomId) {
    socket.leave(roomId);
    
    // 清理房间数据
    if (rooms.has(roomId)) {
      rooms.get(roomId).delete(socket.id);
      if (rooms.get(roomId).size === 0) {
        rooms.delete(roomId);
      }
    }
    
    // 通知其他用户
    socket.to(roomId).emit('user-left', socket.id);
    
    // 清理麦位
    if (micMap.has(roomId)) {
      const micList = micMap.get(roomId);
      const index = micList.indexOf(socket.id);
      if (index !== -1) {
        micList[index] = null;
        micMap.set(roomId, micList);
        io.to(roomId).emit('mic-list', micList);
      }
    }
    
    // 清理禁麦列表
    if (muteMap.has(roomId)) {
      muteMap.get(roomId).delete(socket.id);
    }
    
    // 处理主持人转让
    if (hostMap.get(roomId) === socket.id) {
      const room = rooms.get(roomId);
      let newHost = null;
      if (room && room.size > 0) {
        newHost = Array.from(room)[0];
      }
      if (newHost) {
        hostMap.set(roomId, newHost);
        io.to(roomId).emit('host-info', newHost);
      } else {
        hostMap.delete(roomId);
      }
    }
    
    // 发送离开消息
    if (userInfoMap.has(roomId)) {
      const info = userInfoMap.get(roomId)?.get(socket.id);
      if (info) {
        sendSystemMsg(roomId, `${info.nickname || socket.id} 离开了房间`);
        userInfoMap.get(roomId).delete(socket.id);
      }
    }
    
    // 更新用户列表
    if (userInfoMap.has(roomId)) {
      const userList = Array.from(userInfoMap.get(roomId).entries()).map(([id, info]) => ({
        id,
        nickname: info.nickname || '匿名',
        avatar: info.avatar || ''
      }));
      io.to(roomId).emit('user-list', userList);
    }
  }

  // 系统消息工具
  function sendSystemMsg(roomId, content) {
    io.to(roomId).emit('receive-message', {
      id: 'system',
      message: content,
      time: Date.now(),
      type: 'system'
    });
  }
}; 